package com.zp.security.oauth2.customized;

import org.springframework.security.authentication.AccountStatusException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 自定义邮件TokenGranter,类似于密码模式的ResourceOwnerPasswordTokenGranter
 *
 * @author zp
 */
public class EmailTokenGranter extends AbstractTokenGranter {

    private static final String GRANT_TYPE="email_password";

    private final AuthenticationManager authenticationManager;

    public EmailTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
        super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
        this.authenticationManager = authenticationManager;
    }

    protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
        Map<String, String> requestParameters =new LinkedHashMap<>(tokenRequest.getRequestParameters());
        String email = requestParameters.get("email");
        String password = requestParameters.get("password");
        //将其从参数移除，为了保证安全性
        requestParameters.remove("password");
        EmailAuthenticationToken authenticationToken=new EmailAuthenticationToken(email,password);
        authenticationToken.setDetails(requestParameters);
        //调用authenticationManager获取对应的用户认证信息
        Authentication authenticate;
        try {
            authenticate = authenticationManager.authenticate(authenticationToken);

        }catch (AccountStatusException var8) {
            throw new InvalidGrantException(var8.getMessage());
        } catch (BadCredentialsException var9) {
            throw new InvalidGrantException(var9.getMessage());
        }

        if (authenticate != null && authenticate.isAuthenticated()) {
            OAuth2Request storedOAuth2Request = this.getRequestFactory().createOAuth2Request(client, tokenRequest);
            return new OAuth2Authentication(storedOAuth2Request, authenticate);
        } else {
            throw new InvalidGrantException("Could not authenticate user: " + email);
        }

    }

}
